home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 7
/
Apprentice-Release7.iso
/
Source Code
/
Pascal
/
Applications
/
NIH Image 1.62b11
/
Macros
/
FFT Macros
< prev
next >
Wrap
Text File
|
1996-06-10
|
10KB
|
420 lines
var {global }
FilterSize: real; {0-100% of image size}
TransitionWidth: real; {0-100% of filter radius}
PlotFilter: boolean;
macro 'FFT [F]';
begin
fft('foreward');
end;
macro 'Abitrary Selection FFT [A]';
var
pid1, pid2, x, y, w,h, size: integer;
scale: real;
begin
GetRoi(x, y, w, h);
if w = y then begin
SelectAll;
GetRoi(x, y, w, h);
end;
if w > h then begin
x := x + (w - h) div 2;
w := h;
MakeRoi(x, y, w, hª);
end;
if h > w then begin
y := y+ (h - w) div 2;
h := w;
MakeRoi(x, y, w, h);
end;
size := 2048;
if w <= 32 then size := 32
else if w <= 64 then size := 64
else if w <= 128 then size := 128
else if w <= 256 then size := 256
else if w <= 512 then size := 512
else if w <= 1024 then size := 1024;
scale := size / w;
SetScaling('Bilinear; New Window');
ScaleAndRotate(scale, scale, 0);
pid1 := pidNumber;
fft('foreward');
pid2 := pidNumber;
SelectPic(pid1);
dispose;
SelectPic(pid2);
end;
macro 'Inverse FFT [I]';
begin
fft('Inverse');
end;
macro 'Inverse FFT with Custom Mask [M]';
var
w,h, pixWidth, i, nSmooths: integer;
begin
GetPicSize(w, h);
GetHistogram(0, 0, w,h);
if (histogram[0] = 0) and (histogram[255] = 0) then begin
PutMessage('No mask. You need to edit the power spectrum using black to pass frequencies or white to filter freqwencies.');
exit;
end;
pixWidth := GetNumber('Transition Width in Pixels:', 6, 0);
nSmooths := pixWidth div 2;
if histogram[0] <> 0 then
ChangeValues(1, 255, 255)
else
ChangeValues(0, 254, 0);
for i := 1 to nSmooths do
filter('smooth more');
fft('Inverse with Filter');
end;
macro 'Inverse FFT with Filter';
begin
fft('Inverse with Filter');
end;
{
procedure fftFilter(type: string; percent: integer);
var
width, height, size, loc: integer;
begin
if percent < 0 then
percent := 0;
if percent > 100 then
percent := 100;
SaveState;
fft('foreward');
GetPicSize(width, height);
size := round(( percent/100) * width);
loc := width div 2 - size/2;
MakeOvalRoi(loc, loc, size, size);
if type = 'high' then
SetForeground(0)
else
SetForeground(255);
Fill;
fft('Inverse');
RestoreState;
end;
macro 'High Pass Filter... [H]';
var
percent: integer;
begin
percent := GetNumber('Filter size (0-100%):', 10, 0);
fftFilter('high', percent);
end;
macro 'Low Pass Filter... [L]';
var
percent: integer;
begin
percent := GetNumber('Filter size (0-100%):', 20, 0);
fftFilter('low', percent);
end;
}
procedure MakeFilter(size, tWidth, min, max: real);
var
width, height, roiSize: integer;
pixWidth, i, loc, v: integer;
begin
SaveState;
if size > 100 then size := 100;
if size < 0 then size := 0;
if tWidth > 100 then tWidth := 100;
if tWidth < 0 then tWidth := 0;
if min > 100 then min := 100;
if min < 0 then min := 0;
if max > 100 then max := 100;
if max < 0 then max := 0;
if min > max then min := max;
GetPicSize(width, height);
SelectAll;
size := round(size / 100 * width);
min := round(min / 100 * 255);
max := round(max / 100 * 255);
Setbackground(min);
Clear;
roiSize := size;
pixWidth := round(size div 2 * (tWidth/100));
if pixWidth < 1 then
pixWidth := 1;
for i := 1 to pixWidth do begin
loc := width div 2 - roiSize/2;
MakeOvalRoi(loc, loc, roiSize, roiSize);
v := (max-min) * exp(-4.5 * sqr(1 - i / pixWidth)) + min; {gaussian shape}
SetForeground(v);
Fill;
roiSize := roiSize - 2;
end;
KillRoi;
RestoreState;
end;
procedure doFilter(filterType: string);
var
width, height: integer;
begin
if FilterSize = 0 then
FilterSize := 20;
if TransitionWidth = 0 then
TransitionWidth := 50;
FilterSize := GetNumber('Filter size (0-100%):', FilterSize, 0);
TransitionWidth := GetNumber('Transition Width (0-100%):', TransitionWidth, 0);
if TransitionWidth = 0 then
TransitionWidth := 0.0001;
fft('foreward');
MakeFilter(FilterSize, TransitionWidth, 0, 100);
if FilterType = 'high' then
Invert;
if PlotFilter then begin
getPicSize(width, height);
MakeLineRoi(0, height / 2, width, height / 2);
PlotProfile;
KillRoi;
end;
fft('Inverse with Filter');
end;
macro '(---'; begin end;
macro 'High Pass Filter... [H]';
begin
doFilter('high');
end;
macro 'Low Pass Filter... [L]';
begin
doFilter('low');
end;
macro 'Toggle Filter Plotting ... [T]';
begin
if PlotFilter then begin
PlotFilter := false;
PutMessage('Filter profiles will not be plotted.');
end else begin
PlotFilter := true;
PutMessage('Filter profiles will be plotted.');
end;
end;
macro '(---'; begin end;
macro 'Autocorrelation';
var
fft1, fft2: integer;
begin
fft('foreward');
fft1 := pidNumber;
ImageMath('cmul', fft1, fft1, 1, 0, 'FFT2');
fft2 := pidNumber;
SelectPic(fft1);
Dispose;
SelectPic(fft2);
fft('Inverse');
fft('Swap Quadrants');
SetPicName('Autocorrelation')
end;
macro 'Autocorrelation with Padding';
var
pad, fft1, fft2: integer;
width, height: integer;
n,mean,mode,min,max: real;
begin
SelectAll;
Measure;
GetResults(n,mean,mode,min,max);
Copy;
GetPicSize(width, height);
SetNewSize(width * 2, height * 2);
Setbackgrount(round(mean));
MakeNewWindow('Padded Image');
MakeRoi(0, 0, width, height);
Paste;
KillRoi;
pad := pidNumber;
fft('foreward');
fft1 := pidNumber;
ImageMath('cmul', fft1, fft1, 1, 0, 'FFT2');
fft2 := pidNumber;
SelectPic(pad);
Dispose;
SelectPic(fft1);
Dispose;
SelectPic(fft2);
fft('Inverse');
fft('Swap Quadrants');
SetPicName('Autocorrelation')
end;
macro 'Correlate Two Images' ;
var
pic1, pic2, fft1, fft2, out: integer;
begin
if nPics <> 2 then begin
PutMessage('Exactly two images required.');
exit;
end;
pic1 := pidNumber;
NextWindow;
pic2 := pidNumber;
fft('foreward');
fft2 := pidNumber;
SelectPic(pic1);
fft('foreward');
fft1 := pidNumber;
ImageMath('cmul', fft1, fft2, 1, 0, 'FFT2');
out := pidNumber;
SelectPic(fft1);
Dispose;
SelectPic(fft2);
Dispose;
SelectPic(out);
fft('Inverse');
fft('Swap Quadrants');
SetPicName('Correlation');
SurfacePlot;
end;
macro '(---'; begin end;
macro 'Make Filter...';
var
width, height: integer;
begin
if FilterSize = 0 then
FilterSize := 20;
if TransitionWidth = 0 then
TransitionWidth := 50;
FilterSize := GetNumber('Filter size (0-100%):', FilterSize, 0);
TransitionWidth := GetNumber('Transition Width (0-100%):', TransitionWidth, 0);
if TransitionWidth = 0 then
TransitionWidth := 0.0001;
Duplicate('Filter');
MakeFilter(FilterSize, TransitionWidth, 0, 100);
end;
macro 'Redisplay Power Spectrum';
begin
fft('Display Power Spectrum');
end;
macro 'Swap Quadrants';
begin
fft('Swap Quadrants');
end;
macro '(---'; begin end;
procedure roi(size: integer);
var
width, height: integer;
begin
GetPicSize(width, height);
if size > width then
size := width;
if width = 0 then begin
PutMessage('No image window open.');
exit;
end;
MakeRoi(width/2 - size/2, height/2 - size/2, size, size);
end;
macro 'Create 32 x 32 selection [1]'; begin roi(32) end;
macro 'Create 64 x 64 selection [2]'; begin roi(64) end;
macro 'Create 128 x 128 selection [3]'; begin roi(128) end;
macro 'Create 256 x 256 selection [4]'; begin roi(256) end;
macro 'Create 512 x 512 selection [5]'; begin roi(512) end;
procedure AnnularSelection(color: integer);
var
x1,x2,y1,y2,top,left,width,height, w, h:integer;
xcenter,ycenter,radius1, radius2:integer;
begin
if pos('FFT',WindowTitle) <> 1 then begin
beep;
PutMessage('Frequency domain (FFT) image required.');
exit;
end;
GetPicSize(w,h);
GetLine(x1,y1,x2,y2,width);
if x1<0 then begin
beep;
PutMessage('Line selection required.');
exit;
end;
SaveState;
SetForeground(color);
xcenter:=w/2;
ycenter:=h/2;
radius1:=sqrt(sqr(abs(x1-xcenter))+sqr(abs(y1-ycenter)));
radius2:=sqrt(sqr(abs(x2-xcenter))+sqr(abs(y2-ycenter)));
if radius1 < radius2 then begin
MakeOvalROI(xcenter-radius1,ycenter-radius1,radius1*2,radius1*2);
copy;
setbackgroundcolor(0);
MakeOvalROI(xcenter-radius2,ycenter-radius2,radius2*2,radius2*2);
fill;
paste;
killroi;
end;
MakeOvalROI(xcenter-radius2,ycenter-radius2,radius2*2,radius2*2);
copy;
setbackgroundcolor(0);
MakeOvalROI(xcenter-radius1,ycenter-radius1,radius1*2,radius1*2);
fill;
paste;
killroi;
RestoreState;
end;
macro '(---'; begin end;
{The annular selection macros are designed to be used in the power
spectrum window. Using the line selection tool, a line is drawn that
extends through some range of spatial frequencies. This line should be radial
from the center of the window since the selection will be from the central to
distal portion of the line. After making the line selection, typing W will
cause a black annular selection to be made. Following this selection with the
Inverse command from the FFT macros will result in passing the range of
frequencies selected in the inverse transform. If you want to use the selection
as a notch filter, then type W to create a white annular selection.}
macro 'Black Annular Selection - Pass [B]';
begin
AnnularSelection(255);
end;
macro 'White Annular Selection - Notch [W]';
begin
AnnularSelection(0);
end;